using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Threading.Tasks;
using Net.Common;
using ProtoBuf;
using UnityEngine;

/****************************************************
// 功能：客户端请求网络 TCP
// | Talk To [ 聊来改善地区金融服务环境，助力企业发展 ]
// | Copyright (c) 2021-2025 聊来 All rights reserved.
// | Licensed ( <a href="http://www.apache.org/licenses/LICENSE-2.0">聊来</a> )
// | @Author: 贯彻己道的云 <18970881148@qq.com>
// | DateTime: 2025/2/11 14:34:18
*****************************************************/

public class ClientTcp : SingletonPatternBase<ClientTcp>
{
    private TcpClient tcp;
    private NetworkStream stream;
    private int count;
    private readonly Queue<MsgInfo> delayMsgInfo = new Queue<MsgInfo>();
    public static event Action<MsgInfo> handleController;

    #region Tcp

    /// <summary>
    /// 连接TCP服务器
    /// </summary>
    public async void Connect()
    {
        count = 1;
        await ConnectTcp();
    }
    
    
    private async Task ConnectTcp()
    {
        try
        {
            tcp = new TcpClient();
            await tcp.ConnectAsync(Constants.TCP_ADDRESS, Constants.TCP_PORT);

            // 启动消息接收线程
            _ = Task.Run(ReceiveMessage);
        }
        catch (Exception e)
        {
            HandleTcpMsgInfo(RequestType.CONNECTION_REFUSED,$"TCP连接被拒绝，执行重连第{count}次，错误代码：{e.Message}");
            if (count < 5) { await Reconnect(); }
        }
    }

    /// <summary>
    /// 接收TCP服务端发送的消息
    /// </summary>
    private void ReceiveMessage()
    {
        stream = tcp.GetStream();
        try
        {
            while (tcp.Connected)
            {
                var msg = Serializer.DeserializeWithLengthPrefix<MsgInfo>(stream, PrefixStyle.Base128);
                if (msg != null)
                {
                    HandleTcpMsgInfo(msg.requestType, msg.data);
                }
            }
        }
        catch (Exception e)
        {
            Debug.LogError($"接收TCP发送的消息失败：{e.Message}");
        }
    }
    
    
    /// <summary>
    /// 重连
    /// </summary>
    private async Task Reconnect()
    {
        count++;
        await Task.Delay(TimeSpan.FromSeconds(1f));
        await ConnectTcp();
    }
    
    /// <summary>
    /// 向TCP服务端发送消息
    /// </summary>
    /// <param name="msg"></param>
    public async void Send(MsgInfo msg)
    {
        try
        {
            using var memory = new MemoryStream();
            Serializer.SerializeWithLengthPrefix(memory, msg, PrefixStyle.Base128);
            var buffer = memory.ToArray();
            await stream.WriteAsync(buffer, 0, buffer.Length);
        }
        catch (Exception e)
        {
            // 后面直接用弹出框做提示
            Debug.LogError($"向TCP服务端发送消息失效，执行从连操作：{e.Message}");
            count = 0;
            await Reconnect();
        }
    }

    /// <summary>
    /// 解析TCP服务端发送的消息到队列中
    /// </summary>
    /// <param name="type"></param>
    /// <param name="data"></param>
    public void HandleTcpMsgInfo(RequestType type, string data)
    {
        lock (delayMsgInfo)
        {
            delayMsgInfo.Enqueue(new MsgInfo()
            {
                requestType = type,
                data = data
            });
        }
    }
    #endregion

    
    

    /// <summary>
    /// 派发消息
    /// </summary>
    public void Dispatch()
    {
        lock (delayMsgInfo)
        {
            if (delayMsgInfo.Count <= 0) return;
            var list = delayMsgInfo.ToArray();
            delayMsgInfo.Clear();
            foreach (var msgInfo in list)
            {
                handleController?.Invoke(msgInfo);
            }
        }
    }

    /// <summary>
    /// 断开连接
    /// </summary>
    public void Disconnect()
    {
        if (tcp is not { Connected: true }) return;

        // 非正常退出房间发送消息
        Debug.LogError("非正常关闭应用 - TCP");

        stream.Close();
        tcp.Close();
    }

}